
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <string.h>
#include <fcntl.h>

#define BUFFER	20
#define	DEVICE	"/dev/memio0"

pid_t child = 0;
int pipefd[ 2 ];
char SPAM[ 10 ] = { 'Z', 'Z', 'Z', 'Z', 'Z', 'Z', 'Z', 'Z', 'Z', 'Z' };

void parent_func( int fd )
{
	static char inbuffer[ BUFFER ];
	ssize_t rv = 0;
	int dd = open( DEVICE, O_RDONLY );
	if ( dd == -1 ) {
		perror( "Can't open file " DEVICE );
		return;
	}
	lseek( dd, 512, SEEK_SET );
	do {
		rv = read( fd, inbuffer, BUFFER - 1 );
		if ( rv < 0 ) {
			perror("Parent read error");
			return;
		}
		inbuffer[ rv ] = '\0';
		printf ( "Parent get: %s\n", inbuffer );
		if ( strncmp( inbuffer, "OK", 3 ) == 0 ) {
			break;
		}
		rv = read ( dd, inbuffer, BUFFER - 1 );
		if ( rv < 0 ) {
			perror("Device read error");
			return;
		}
		inbuffer[ rv ] = '\0';
		printf ( "Read from device: %s\n", inbuffer );
		lseek( dd, -rv, SEEK_CUR );
	} while ( 1 );
	close ( dd );
	return;
}

void child_func( int fd )
{
//	int downcount = 10;
	int dd = open( DEVICE, O_RDWR );
	if ( dd == -1 ) {
		write( fd, "OK", 3 );
		return;
	}
	do {
		write( fd, "READ", 5 );
		sleep( 1 );
		lseek( dd, 512, SEEK_SET );
		write( dd, SPAM, 10 );
		write( fd, "READ", 5 );
		sleep( 20 );
	} while ( /*--downcount != 0*/ 0 );
	write( fd, "OK", 3 );
	close ( dd );
	return;
}

int main ( int argc, char* argv[] ) {
	pid_t rv = 0;
	int status = 0;

	if ( pipe(pipefd) == -1 ) {
		perror( "pipe" );
		exit( EXIT_FAILURE );
	}

	child = fork();
	if (child==-1) {
		perror( "fork" );
		exit( EXIT_FAILURE );
	}

	if ( child ) {	// parent process
		close( pipefd[ 1 ] );
		parent_func( pipefd[0] );
		do {
			rv = waitpid( child, &status, WNOHANG );
		} while ( rv == 0 );
		close( pipefd[ 0 ] );
	} else {		// child process
		close( pipefd[ 0 ] );
		child_func( pipefd[1] );
		close( pipefd[ 1 ] );
	}
	return 0;
}
